import React, { useState, useEffect } from 'react';
import { urlGet, urlMd, MDel, Mcmd, obj_empty, obj_bool, obj_str, FitWidth, MaTable, IkCheck, useForm, cline, Btn, useCmd, is_empty, Ret, WaitUmd,
    CkValue, ck_ascii, ck_empty, useCheck, IkInput, split_md, Dlg, MainView, PanelTitle } from '../../nui';
import { loc } from '../../local';

const Edit = ({ open, setOpen, hcmd, cur }) => {
    const [value, setValue] = useState();
    const form = useForm(setValue);
    const [open_ck, openCk, hcheck] = useCheck();

    useEffect(() => {
        if (!open) {
            return;
        }

        if (obj_empty(cur)) {
            setValue(null);
            return;
        }

        setValue({
            sn: obj_str(cur, "sn"),
            name: obj_str(cur, "name"),
            opt: obj_bool(cur, "opt"),
        });
    }, [cur, open]);

    const hdone = () => {
        const ck = {
            sn: (v) => ck_ascii(v, loc("bh")),
            name: (v) => ck_empty(v, loc("mc")),
        };

        if (!form.hcheck(ck, value)) {
            return;
        }

        setOpen(false);
        hcmd(value);
    };

    const ckdes = {
        "sn": loc("bh"),
        "name": loc("mc"),
    };

    return (
        <Dlg open={open} hcmd={() => hcheck(value, ckdes, hdone)} title={loc("zdy")} hcancel={() => setOpen(false)}>
            <IkInput name="sn" label={ckdes["sn"]} form={form} value={value}/>
            <IkInput name="name" label={ckdes["name"]} form={form} value={value}/>
            <IkCheck name="opt" label={loc("xtzd")} value={value} form={form}/>
            <CkValue setOpen={openCk} open={open_ck} value={value} des={ckdes} setValue={setValue} hcmd={hdone}/>
        </Dlg>
    );
};

const reload = (fnDone, mod, setMain) => urlGet(fnDone,
    {
        n: "cfg",
        obj: "uid,km,kv,skm,skv",
        opt: {
            and: [{eq: "sn", v: mod}]
        }
    },
    r => {
        const data = r[0];

        const ret = {
            uid: data.uid,
            data: [],
        };

        const [km, kv] = split_md(data, "kv", "km");
        const [skm, skv] = split_md(data, "skv", "skm");

        if (!is_empty(km)) {
            km.forEach((d, i) => ret.data.push({sn: d, name: kv[i], opt: false}));
        }

        if (!is_empty(skm)) {
            skm.forEach((d, i) => ret.data.push({sn: d, name: skv[i], opt: true}));
        }

        setMain(ret);
    },
    e => setMain(null)
);

const Cfg = ({ hreturn, sideopen, mod, title }) => {
    const umd = useCmd(null, "cfg");
    const [open, setOpen] = useState(false);
    const [main, setMain] = useState(null);

    useEffect(() => reload(null, mod, setMain), [mod]);

    const getData = (data) => {
        const tmp = [];

        const km = [];
        const kv = [];
        const skm = [];
        const skv = [];

        data.forEach(d => {
            if (d.opt) {
                skm.push(d.sn);
                skv.push(d.name);
            }
            else {
                km.push(d.sn);
                kv.push(d.name);
            }
        });

        if (is_empty(km)) {
            tmp.push({k: "km", v: ""});
            tmp.push({k: "kv", v: ""});
        }
        else {
            tmp.push({k: "km", v: km.join(",")});
            tmp.push({k: "kv", v: kv.join(",")});
        }

        if (is_empty(skm)) {
            tmp.push({k: "skm", v: ""});
            tmp.push({k: "skv", v: ""});
        }
        else {
            tmp.push({k: "skm", v: skm.join(",")});
            tmp.push({k: "skv", v: skv.join(",")});
        }

        return tmp;
    };

    const hsub = (v) => {
        const sn = v.sn;
        const name = v.name;
        const opt = v.opt;

        umd.startWait();

        let cmd = {};

        if (obj_empty(main) || !main.uid) {
            const tmp = [
                {k: "sn", v: mod},
            ];

            if (opt) {
                tmp.push({k: "skm", v: sn});
                tmp.push({k: "skv", v: name});
            }
            else {
                tmp.push({k: "km", v: sn});
                tmp.push({k: "kv", v: name});
            }

            cmd["a"] = [{
                u: cline(),
                n: "cfg",
                v: [tmp]
            }];
        }
        else {
            const uid = main.uid;
            const data = main.data.map(d => {
                return {
                    sn: d.sn,
                    name: d.name,
                    opt: d.opt,
                };
            });

            if (umd.cur) {
                const f = data.find(d => d.sn === umd.cur.sn);
                if (!f) {
                    umd.setWrong(loc("cfg3"));
                    return;
                }

                f["sn"] = sn;
                f["name"] = name;
                f["opt"] = opt;

                const t = data.filter(d => d.sn === sn);
                if (t && t.length !== 1) {
                    umd.setWrong(loc("cfg4"));
                    return;
                }
            }
            else {
                const f = data.find(d => d.sn === sn);
                if (f) {
                    umd.setWrong(loc("cfg4"));
                    return;
                }

                data.push({sn: sn, name: name, opt: opt});
            }

            const tmp = getData(data);
            if (is_empty(tmp)) {
                umd.setWrong(loc("cfg5"));
                return;
            }

            cmd["m"] = [{
                u: uid,
                v: tmp,
            }];
        }

        urlMd(null, cmd, r => reload(umd.endWait, mod, setMain), e => umd.setWrong(loc("xgsb")));
    };

    const hdel = (v) => {
        umd.startWait();

        const uid = main.uid;
        const data = main.data.filter(d => d.sn !== v.sn);

        const tmp = getData(data);
        if (is_empty(tmp)) {
            umd.setWrong(loc("cfg5"));
            return;
        }

        let cmd = {
            m: [{
                u: uid,
                v: tmp,
            }]
        };

        urlMd(null, cmd, r => reload(umd.endWait, mod, setMain), e => umd.setWrong(loc("scsb")));
    };

    const hAction = (d) => {
        umd.hcur(d);
        setOpen(true);
    };

    const getRow = () => {
        if (obj_empty(main)) {
            return null;
        }

        const data = main.data;
        if (is_empty(data)) {
            return null;
        }

        const ret = [];

        data.forEach(d => {
            if (!d.opt) {
                ret.push(d);
            }
        });

        data.forEach(d => {
            if (d.opt) {
                ret.push(d);
            }
        });

        return ret;
    };

    const col = [
        {title: loc("cz"), field: 'e_opt', width: 180, export: false, render: d => {
            return (
                <div className="inline-flex">
                    <MDel uid={d.sn} umd={umd} hcmd={() => hdel(d)}/>
                    <Mcmd uid={d.sn} title={loc("xg")} itype="edit" hcmd={() => hAction(d)}/>
                </div>
            );
        }},
        {title: loc("bh"), field: 'sn'},
        {title: loc("mc"), field: 'name'},
        {title: loc("xx"), field: 'opt', render: r => r.opt ? loc("xt") : loc("bt")},
    ];

    const Title = () => {
        const hdone = () => {
            umd.hcur(null);
            setOpen(true);
        };

        return (
            <Btn name="add" hcmd={hdone}>{loc("tj")}</Btn>
        );
    };

    return (
        <MainView>
            <PanelTitle left={`${title} >> ${loc("zdy")}`} right={<Ret hcmd={hreturn}/>} cl="gray"/>
            <FitWidth sideopen={sideopen}>
                <MaTable
                    title={<Title/>}
                    opt={{
                        tableLayout: "fixed",
                    }}
                    paging={false}
                    col={col}
                    row={getRow()}
                    exbt={false}/>
            </FitWidth>
            <Edit open={open} setOpen={setOpen} cur={umd.cur} hcmd={hsub}/>
            <WaitUmd umd={umd}/>
        </MainView>
    );
};

const get_cfg = (cfg, keym, keyv) => {
    if (obj_empty(cfg)) {
        return null;
    }

    const lst = [];
    const [km, kv] = split_md(cfg, keyv, keym);
    if (!is_empty(km)) {
        km.forEach((d, i) => lst.push({sn: d, name: kv[i]}));
    }

    return lst;
};

const reload_cfg = (mod, setCfg) => urlGet(null,
    {
        n: "cfg",
        obj: "uid,km,kv,skm,skv",
        opt: {
            and: [{eq: "sn", v: mod}]
        }
    },
    r => setCfg(r[0]), e => setCfg(null)
);

const pack_cfg_more = (cfg, pack_fix) => {
    const lst = pack_fix();

    let cfg_lst = [];

    let tmp = get_cfg(cfg, "km", "kv");
    if (!is_empty(tmp)) {
        cfg_lst = tmp;
    }

    tmp = get_cfg(cfg, "skm", "skv");
    if (!is_empty(tmp)) {
        cfg_lst = cfg_lst.concat(tmp);
    }

    if (is_empty(cfg_lst)) {
        return [null, null];
    }

    let set = new Set();
    lst.forEach(d => set.add(d));

    const ret = [];
    const val = [];

    cfg_lst.forEach(d => {
        if (set.has(d.sn)) {
            return;
        }

        ret.push(d.sn);
        val.push(d);
    });

    return [ret, val];
};

const pack_cfg = (cfg, pack_fix) => {
    const lst = pack_fix();

    const [more] = pack_cfg_more(cfg, pack_fix);
    if (is_empty(more)) {
        return lst;
    }

    return lst.concat(more);
};

const pack_lst = (cfg, pack_fix) => {
    let obj = pack_cfg(cfg, pack_fix);
    obj = obj.filter(d => d !== "uid");

    return obj;
};

const pack_reload = (cfg, setMain, mod, pack_fix) => {
    let obj = pack_cfg(cfg, pack_fix);

    const cmd = {
        n: mod,
        obj: obj.join(","),
        opt: {order: "sn"},
    };

    urlGet(null, cmd, r => {
        r.forEach((d, i) => d["index"] = i + 1);
        setMain(r);
    }, e => setMain(null));
};

export {pack_cfg_more, pack_reload, pack_lst, get_cfg, reload_cfg, Cfg};
